package com.firefightingiot.firefightingiot.common.interceptor;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.StrUtil;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.parser.Feature;
import com.firefightingiot.firefightingiot.common.base.BasisEntity;
import com.firefightingiot.firefightingiot.common.utils.Dict;
import com.firefightingiot.firefightingiot.support.annotaion.*;
import com.firefightingiot.firefightingiot.support.annotaion.enums.ExportType;
import com.firefightingiot.firefightingiot.support.annotaion.enums.FileNameType;
import com.firefightingiot.firefightingiot.support.filter.RequestWrapper;
import com.firefightingiot.firefightingiot.support.model.RespEntity;
import com.firefightingiot.firefightingiot.support.utils.entity.Params;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.*;
import java.util.Map.Entry;

/**
 * 参数校验拦截器
 * 
 * @author
 *
 */
public class ParamsInterceptor implements HandlerInterceptor {

	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		Params params = null;
		params = new Params(request);
		if (params == null || params.size() == 0) {
			if (request instanceof MultipartHttpServletRequest) {
			} else {
				RequestWrapper myRequestWrapper = new RequestWrapper(request);
				String body = myRequestWrapper.getBody();
				if (!"".equals(body)) {
					params = new Params(JSONObject.parseObject(body, Feature.OrderedField));
				}
			}
		}
		response.setCharacterEncoding("utf-8");
		response.setContentType("application/json; charset=utf-8");
		HandlerMethod handlerMethod = null;
		if (handler instanceof HandlerMethod) {
			handlerMethod = (HandlerMethod) handler;
		} else {
			return true;
		}
		Method method = handlerMethod.getMethod();
		Object controller = handlerMethod.getBean();

		At at = method.getAnnotation(At.class);
		if (at != null) {
			// 开始做参数校验
			String result = "";
			for (String param : at.param()) {
				if (params.get(param)==null) {
					result += param + ",";
				}
			}
			if (!StrUtil.isBlank(result)) {
				result = result.substring(0, result.length() - 1);
				result = "[" + result + "]";
				response.getWriter().println(RespEntity.fail("缺少必要参数 " + result));
				return false;
			}
			// 开始做参数长度校验
			Len[] lens = at.len();
			Map<String, Object> lenMap = new HashMap<String, Object>(lens.length);
			for (Len len : lens) {
				lenMap.put(len.name(), len.value());
			}
			Dict lenDict = Dict.create(lenMap);
			Iterator<Entry<String, Object>> entries = params.entrySet().iterator();
			while (entries.hasNext()) {
				@SuppressWarnings("rawtypes")
                Entry entry = (Entry) entries.next();
				String name = Convert.toStr(entry.getKey());
				String value = Convert.toStr(entry.getValue());
				int length = lenDict.getInt(name);
				length = length == 0 ? lenDict.getInt("_all_") : length;
				if (length <= 0) {
					continue;
				}
				if (value.length() > length) {
					result += StrUtil.format("{}长度不能超过{},", name, length);
				}
			}

			if (!StrUtil.isBlank(result)) {
				result = result.substring(0, result.length() - 1);
				result = "[" + result + "]";
				response.getWriter().println(RespEntity.fail("参数长度不合法  " + result));
				return false;
			}

		}

		Export export = method.getAnnotation(Export.class);
		if (export != null) {
			if (export.type() == ExportType.EXCEL) {
				Class<?> configClazz = export.configClass();

				String fileName = "";
				RespEntity entity = (RespEntity) method.invoke(controller, (Map<?, ?>) params);
				if ("error".equals(entity.getCode())) {
					return true;
				}

				List<Object> listData = (List<Object>) entity.getData();

				ExcelWriter writer = ExcelUtil.getWriter();
				Map<String, String> keys = null;
				if (configClazz != null && configClazz != ExportConfig.class) {
					Object exportConfig = configClazz.newInstance();
					// 执行参数builder构建
					configClazz.getMethod("builder").invoke(exportConfig);
					fileName = configClazz.getSuperclass().getMethod("getFileName").invoke(exportConfig).toString();
					keys = (Map<String, String>) configClazz.getSuperclass().getMethod("keys").invoke(exportConfig);

				} else {
					if (listData != null && !listData.isEmpty()) {
						Class<?> beanClass = listData.get(0).getClass();
						if (beanClass.getSuperclass() == BasisEntity.class) {
							keys = new HashMap<>();
							// 获取列名对应关系
							for (Field field : beanClass.getDeclaredFields()) {
								ExcelName excelName = field.getAnnotation(ExcelName.class);
								if (excelName != null) {
									keys.put(field.getName(), excelName.value());
								}
							}

						}
					}
				}
				writer.setHeaderAlias(keys);

				if (entity.containsKey("fileName")) {
					fileName = entity.getString("fileName");
				}
				if(export.fileNameType() == FileNameType.UUID) {
					fileName = UUID.randomUUID().toString().replaceAll("-", "");
				}
				if(export.fileNameType() == FileNameType.TIME) {
					fileName = System.currentTimeMillis()+"";
				}
				response.setContentType("application/msexcel;charset=UTF-8");
				response.setHeader("Content-disposition",
						"attachment; filename=" + new String(fileName.getBytes("UTF-8"), "ISO_8859_1") + ".xls");
				writer.write(listData);
				OutputStream out = response.getOutputStream();
				writer.flush(out);
				// 关闭writer，释放内存
				writer.close();
				out.close();
			}
		}
		Import importExcel=method.getAnnotation(Import.class);
		if(importExcel!=null) {
			if(request instanceof MultipartHttpServletRequest) {
				BufferedReader streamReader=new BufferedReader(new InputStreamReader(request.getInputStream()));
				StringBuilder respBuilder=new StringBuilder();
				String inputStr;
				while((inputStr=streamReader.readLine())!=null) {
					respBuilder.append(inputStr);
				}
				JSONObject jsonObject=JSONObject.parseObject(respBuilder.toString());
				if(jsonObject!=null) {
					params.putAll(jsonObject);
				}

				response.setCharacterEncoding("UTF-8");
				response.setContentType("application/json; charset=utf-8");
				MultipartHttpServletRequest multipartHttpServletRequest = (MultipartHttpServletRequest) request;
				//List<MultipartFile> qq = multipartHttpServletRequest.getFiles("file");
				InputStream is = multipartHttpServletRequest.getFile(importExcel.value()).getInputStream();
				ExcelReader reader = ExcelUtil.getReader(is);
				List<?> list;
				if (importExcel.beanType() != ObjectUtils.Null.class) {
					list = reader.read(1, 1, Integer.MAX_VALUE, importExcel.beanType());
				} else {
					list = reader.read(importExcel.titleLine(), importExcel.startLine(), Integer.MAX_VALUE, Map.class);

				}
				params.put(importExcel.dataName(), list);
				RespEntity entity = (RespEntity) method.invoke(controller, (Map<?, ?>) params);
				response.getWriter().print(entity.toJSONString());
				return false;

			}
		}
		
		return true;
	}

}
